接者來快速做一個應用來串接 Keycloak 的登入試試,這邊用的是基於 Nextjs 的 T3 。
pnpm create t3-app@latest
在建立的時候注意要選使用 NextAuth
這邊用的是 Prisma 作為 ORM 搭配 Postgres,專案生成後首先建立資料庫的 Docker 跟將預設的 Schema 同步進去。
bash start-database.sh
pnpm db:push
接下來要設定 NextAuth 使用 Keycloak 登入,官方有對應的 provider 可以使用。
// src/server/auth.ts
import KeycloakProvider from "next-auth/providers/keycloak";
// ...
export const authOptions: NextAuthOptions = {
callbacks: {
session: ({ session, user }) => ({
...session,
user: {
...session.user,
id: user.id,
},
}),
},
adapter: PrismaAdapter(db) as Adapter,
providers: [
KeycloakProvider({
clientId: env.KEYCLOAK_CLIENT_ID!,
clientSecret: env.KEYCLOAK_CLIENT_SECRET!,
issuer: env.KEYCLOAK_ISSUER,
}),
],
};
環境變數參考如下:
KEYCLOAK_ISSUER="http://localhost:8080/realms/awesome" # 執行驗證的 realm 端口
KEYCLOAK_CLIENT_ID="awesome-next"
KEYCLOAK_CLIENT_SECRET="*************************"
KEYCLOAK_CLIENT_SECRET 可以在 Client 中 的 Credential 頁面找到
準備好登入端口後再來啟動專案
pnpm dev
就能試著來用 Keycloak 做登入了
點下去會導向 Keycloak 自己的登入頁面,在那邊登入成功後導向回 Next App 後就會是登入成功的狀態了。
但這邊會有個問題,Keycloak Provider 回傳的 user data 沒有跟 NextAuth 的 Account 資訊對齊,在用 Prisma 寫入時會報錯,所以要做點調整。
// src/server/auth.ts
const adapter = PrismaAdapter(db);
const _linkAccount = adapter.linkAccount;
adapter.linkAccount = (account) => {
// 將沒對上的參數濾出或替換
const { "not-before-policy": _, refresh_expires_in, ...data } = account;
return _linkAccount!({
...data,
refresh_token_expires_in: refresh_expires_in,
});
};